﻿using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace System
{
    public class AsyncActionHelper
    {
        private static ILog _logger = LogManager.GetLogger("TaskHelper");
        private static Dispatcher Dispatcher => Application.Current?.Dispatcher ?? Dispatcher.CurrentDispatcher;

        public static void RunTask(Action action)
        {
            Task.Run(() =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.Message, ex);
                    throw;
                }
            });
        }

        public static Task<TResult> RunTask<TResult>(Func<TResult> action)
        {
            return Task.Run(() =>
            {
                try
                {
                    return action();
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.Message, ex);
                    throw;
                }
            });
        }

        public static void RunTask(Func<Task> action)
        {
            Task.Run(async () =>
            {
                try
                {
                    await action();
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.Message, ex);
                    throw;
                }
            });
        }

        public static Task RunTaskResult(Func<Task> action)
        {
            return Task.Run(async () =>
            {
                try
                {
                    await action();
                }
                catch (Exception ex)
                {
                    _logger.Error(ex.Message, ex);
                    throw;
                }
            });
        }

        public static TResult RunDispatcherTask<TResult>(Func<TResult> action)
        {
            return RunDispatcherTask(action, DispatcherPriority.Normal);
        }

        public static Task<TResult> RunDispatcherTaskAsync<TResult>(Func<TResult> action)
        {
            return RunDispatcherTaskAsync(action, DispatcherPriority.Normal);
        }

        public static void RunDispatcherTask(Action action)
        {
            RunDispatcherTask(action, DispatcherPriority.Normal, true);
        }

        public static void RunDispatcherTask(Action action, DispatcherPriority dispatcher = DispatcherPriority.Normal)
        {
            RunDispatcherTask(action, dispatcher, true);
        }

        public static void RunDispatcherTask(Action action, bool isAsync = true)
        {
            RunDispatcherTask(action, DispatcherPriority.Normal, isAsync);
        }

        public static void RunDispatcherTask(Action action, DispatcherPriority dispatcher = DispatcherPriority.Normal, bool isAsync = true)
        {
            if (isAsync)
            {
                Dispatcher.BeginInvoke(action, dispatcher);
            }
            else
            {
                Dispatcher.Invoke(action, dispatcher);
            }
        }

        public static TResult RunDispatcherTask<TResult>(Func<TResult> action, DispatcherPriority dispatcher = DispatcherPriority.Normal)
        {
            return Dispatcher.Invoke(action, dispatcher);
        }

        public static async Task<TResult> RunDispatcherTaskAsync<TResult>(Func<TResult> action, DispatcherPriority dispatcher = DispatcherPriority.Normal)
        {
            return await Dispatcher.InvokeAsync(action, dispatcher);
        }
    }
}
